package com.example.testble;



import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.concurrent.atomic.AtomicBoolean;

public class UdpBroadcastClient {
    private static final String TAG = UdpBroadcastClient.class.getSimpleName();
    private static final String RECEIVER_THREAD_NAME = "UdpBroadcastReceiverThread";
    private static final int RECEIVE_BUFFER_SIZE = 1024;
    private static final int BROADCAST_PORT = 57997;    //TODO 端口
    private static final String DATA_PREFIX = "[UUID]"; // TODO 协议格式

    private volatile DatagramSocket socket;
    private volatile UdpReceiverThread receiverThread;

    private UdpBroadcastClient() {
        initializeSocket();
    }

    private void initializeSocket() {
        try {
            socket = new DatagramSocket(BROADCAST_PORT);
            socket.setBroadcast(true);
            BLogger.d(TAG, "DatagramSocket initialized on port " + BROADCAST_PORT);
        } catch (SocketException e) {
            BLogger.e(TAG, "Failed to initialize DatagramSocket: " + e.getMessage());
            socket = null;
        }
    }

    private static class SingletonHolder {
        private static final UdpBroadcastClient INSTANCE = new UdpBroadcastClient();
    }

    public static UdpBroadcastClient getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public synchronized void startListening() {
        if (socket == null || socket.isClosed()) {
            initializeSocket();
            if (socket == null) {
                BLogger.e(TAG, "Failed to start listening: socket initialization failed");
                return;
            }
        }
        if (receiverThread != null && receiverThread.isAlive()) {
            BLogger.d(TAG, "Receiver thread already running, restarting...");
            stopListening();
        }
        receiverThread = new UdpReceiverThread();
        receiverThread.start();
        BLogger.d(TAG, "Started UDP broadcast receiver on port " + BROADCAST_PORT);
    }

    public synchronized void stopListening() {
        BLogger.d(TAG, "Stopping UDP broadcast receiver");
        if (receiverThread != null) {
            receiverThread.cancel();
            try {
                receiverThread.join(1000);
            } catch (InterruptedException e) {
                BLogger.w(TAG, "Interrupted while waiting for receiver thread to stop");
                Thread.currentThread().interrupt();
            }
            receiverThread = null;
        }
        if (socket != null) {
            socket.close();
            socket = null;
        }
    }

    private class UdpReceiverThread extends Thread {
        private final AtomicBoolean isRunning = new AtomicBoolean(true);
        private final byte[] receiveBuffer = new byte[RECEIVE_BUFFER_SIZE];

        public UdpReceiverThread() {
            super(RECEIVER_THREAD_NAME);
            BLogger.d(TAG, "UdpReceiverThread created");
        }

        public void cancel() {
            isRunning.set(false);
            if (socket != null && !socket.isClosed()) {
                socket.close(); // 关闭socket以中断receive()
            }
        }

        @Override
        public void run() {
            while (isRunning.get() && socket != null && !socket.isClosed()) {
                try {
                    DatagramPacket packet = new DatagramPacket(receiveBuffer, receiveBuffer.length);
                    socket.receive(packet);
                    String receivedData = new String(packet.getData(), 0, packet.getLength()).trim();

                    String decryptedData = AESUtil.decrypt(receivedData);
                    if (decryptedData == null) {
                        BLogger.w(TAG, "Failed to decrypt received data");
                        continue;
                    }

                    BLogger.d(TAG, "Received broadcast on port " + BROADCAST_PORT + ": " + decryptedData);

                    // TODO 提交给BleGattClient去扫描
                    if (decryptedData.startsWith(DATA_PREFIX)) {
                        String uuid = decryptedData.substring(DATA_PREFIX.length());
                        BleGattClient.getInstance().handleServiceId(uuid);
                    }
                } catch (IOException e) {
                    if (isRunning.get()) {
                        BLogger.e(TAG, "IOException during receive: " + e.getMessage());
                    }
                } catch (Exception e) {
                    if (isRunning.get()) {
                        BLogger.e(TAG, "Unexpected error during receive: " + e.getMessage());
                    }
                }
            }
            BLogger.d(TAG, "UdpReceiverThread stopped");
        }
    }
}
